package ns2;

import java.io.Serializable;
import java.util.Vector;

import util.Nodes;
import util.Traces;

public class Topology implements Serializable {

	private static final long serialVersionUID = 123L;

	public Nodes nodes;

	public Topology() {
		this.nodes = new Nodes();
	}

	public void update(Traces traces) {
		this.update(traces, 0, traces.size() - 1);
	}

	public void update(Traces traces, float start, float end) {
		this.reset();
		int startingPoint = 0;
		int endingPoint = traces.size() - 1;
		while (traces.traceAt(startingPoint).time < start) {
			startingPoint++;
		}
		while (traces.traceAt(endingPoint).time > end) {
			endingPoint--;
		}
		for (int i = startingPoint; i <= endingPoint; i++) {
			if (traces.traceAt(i).to_node.id != 0) { // Node 0 represents ISP
				Node node = this.nodes.getNode(traces.traceAt(i).to_node.id);
				node.log(traces.traceAt(i));
			}
		}
		this.buildConnectionsTable();
		this.compact();
	}

	private void compact() {
		this.nodes.compact();
		for (int i = 0; i < this.nodes.size(); i++) {
			this.nodes.nodeAt(i).compact();
		}
	}

	private void buildConnectionsTable() {
		for (int n = 0; n < this.nodes.size(); n++) {
			// Group all traces depends on the traces source addresses.
			Vector<Traces> groupBySources = this.nodes.nodeAt(n).allTraces
					.sort(Field.Src_addr);
			// For each of the source addresses, group traces depending on their
			// destinations.
			for (int i = 0; i < groupBySources.size(); i++) {
				Vector<Traces> groupByDst = groupBySources.elementAt(i).sort(
						Field.Dst_addr);
				for (int j = 0; j < groupByDst.size(); j++) {
					this.nodes.nodeAt(n).connections
							.addConnection(new Connection(groupByDst.elementAt(
									j).traceAt(0)));
				}
			}

			for (int k = 0; k < this.nodes.nodeAt(n).allTraces.size(); k++) {
				if (this.nodes.nodeAt(n).allTraces.traceAt(k).src_addr.port == 911) {
					this.nodes.nodeAt(n).intrusionTraces.add(this.nodes
							.nodeAt(n).allTraces.traceAt(k));
				} else {
					this.nodes.nodeAt(n).normalTraces
							.add(this.nodes.nodeAt(n).allTraces.traceAt(k));
				}
			}
		}
	}

	private void reset() {
		for (int i = 0; i < this.nodes.size(); i++) {
			this.nodes.nodeAt(i).reset();
		}
	}

	public int getNumberOfNodes() {
		return this.nodes.size();
	}

}